/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 carryover_data.h

	$Header: /heroes4/carryover_data.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( CARRYOVER_DATA_H_INCLUDED )
#define CARRYOVER_DATA_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <algorithm>
#include <assert.h>
#include <iosfwd>
#include <string>
#include <vector>

#include "artifact.h"
#include "artifact_set.h"
#include "artifact_slot.h"
#include "carryover_data_ptr.h"
#include "counted_ptr.h"
#include "creature_stack.h"
#include "hero_class.h"
#include "player_color.h"
#include "skill.h"
#include "spell_set.h"
#include "town_type.h"

// --------------------------------------------------------------------------
// t_hero_carryover_data class
// --------------------------------------------------------------------------

class t_hero_carryover_data : public t_counted_object
{
public:
	// Typedef
	typedef std::vector< t_artifact > t_backpack;

	// Constructors
	t_hero_carryover_data();

	// Member functions
	t_town_type			get_alignment() const;
	t_artifact const &	get_artifact( t_artifact_slot slot ) const;
	t_backpack const &	get_backpack() const;
	std::string const &	get_biography() const;
	int					get_biography_id() const;
	int					get_bonus( t_stat_type stat_type ) const;
	int					get_experience() const;
	t_hero_class		get_class() const;
	std::string const &	get_name() const;
	int					get_portrait_id() const;
	t_skill_mastery		get_mastery( t_skill_type skill ) const;
	t_spell_set const &	get_spellbook() const;
	bool				is_male() const;
	bool				is_named_by_map() const;
	bool				read( std::streambuf & stream, int real_format_version = -1 );
	void				set_alignment( t_town_type new_alignment );
	void				set_artifact( t_artifact_slot slot, t_artifact const & new_artifact );
	void				set_backpack( t_backpack const & new_backpack );
	void				set_biography( std::string const & new_biography );
	void				set_biography_id( int new_biography_id );
	void				set_bonuses( int const ( & new_bonuses )[ k_stat_type_count ] );
	void				set_experience( int new_experience );
	void				set_class( t_hero_class new_class );
	void				set_is_male( bool new_is_male );
	void				set_name( std::string const & new_name );
	void				set_is_named_by_map( bool new_is_named_by_map );
	void				set_portrait_id( int new_portrait_id );
	void				set_mastery( t_skill_type skill, t_skill_mastery new_mastery );
	void				set_spellbook( t_spell_set const & new_spellbook );
	void				set_use_spellcaster_model( bool arg );
	bool				use_spellcaster_model() const;
	bool				write( std::streambuf & stream ) const;
	
private:
	// Data members
	t_town_type		m_alignment;
	t_artifact		m_artifacts[ k_artifact_slot_hero_count ];
	t_backpack		m_backpack;
	std::string		m_biography;
	int				m_biography_id;
	int				m_bonuses[ k_stat_type_count ];
	int				m_experience;
	t_hero_class	m_class;
	bool			m_male;
	std::string		m_name;
	bool			m_named_by_map;
	int				m_portrait_id;
	t_skill_mastery	m_skill_masteries[ k_skill_type_count ];
	t_spell_set		m_spellbook;
	bool			m_use_spellcaster_model;
};

// --------------------------------------------------------------------------
// t_hero_carryover_data inline members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_town_type t_hero_carryover_data::get_alignment() const
{
	return m_alignment;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_artifact const & t_hero_carryover_data::get_artifact(
	t_artifact_slot	slot ) const
{
	assert( slot >= 0 && slot < k_artifact_slot_hero_count );
	return m_artifacts[ slot ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_hero_carryover_data::t_backpack const &
t_hero_carryover_data::get_backpack() const
{
	return m_backpack;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline std::string const & t_hero_carryover_data::get_biography() const
{
	return m_biography;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline int t_hero_carryover_data::get_biography_id() const
{
	return m_biography_id;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline int t_hero_carryover_data::get_bonus( t_stat_type stat_type ) const
{
	assert( stat_type >= 0 && stat_type < k_stat_type_count );
	return m_bonuses[ stat_type ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline int t_hero_carryover_data::get_experience() const
{
	return m_experience;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_hero_class t_hero_carryover_data::get_class() const
{
	return m_class;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline std::string const & t_hero_carryover_data::get_name() const
{
	return m_name;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline int t_hero_carryover_data::get_portrait_id() const
{
	return m_portrait_id;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_skill_mastery t_hero_carryover_data::get_mastery(
	t_skill_type	skill ) const
{
	assert( skill >= 0 && skill < k_skill_type_count );
	return m_skill_masteries[ skill ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_spell_set const & t_hero_carryover_data::get_spellbook() const
{
	return m_spellbook;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline bool t_hero_carryover_data::is_male() const
{
	return m_male;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline bool t_hero_carryover_data::is_named_by_map() const
{
	return m_named_by_map;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_alignment( t_town_type new_alignment )
{
	assert( new_alignment >= 0 && new_alignment < k_town_type_count );
	m_alignment = new_alignment;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_artifact(
	t_artifact_slot		slot,
	t_artifact const &	new_artifact )
{
	assert( slot >= 0 && slot < k_artifact_slot_hero_count );
	m_artifacts[ slot ] = new_artifact;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_backpack(
	t_backpack const &	new_backpack )
{
	m_backpack = new_backpack;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_biography(
	std::string const &	new_biography )
{
	m_biography = new_biography;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_biography_id( int new_biography_id )
{
	m_biography_id = new_biography_id;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_bonuses(
	int const ( &	new_bonuses )[ k_stat_type_count ] )
{
	std::copy( new_bonuses, new_bonuses + k_stat_type_count, m_bonuses );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_experience( int new_experience )
{
	m_experience = new_experience;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_class( t_hero_class new_class )
{
	assert( new_class >= 0 && new_class < k_hero_class_count );
	m_class = new_class;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_is_male( bool new_is_male )
{
	m_male = new_is_male;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_name( std::string const & new_name )
{
	m_name = new_name;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_is_named_by_map(
	bool	new_is_named_by_map )
{
	m_named_by_map = new_is_named_by_map;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_portrait_id( int new_portrait_id )
{
	m_portrait_id = new_portrait_id;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_mastery(
	t_skill_type	skill,
	t_skill_mastery	new_mastery )
{
	assert( skill >= 0 && skill < k_skill_type_count );
	assert( new_mastery >= k_mastery_none && new_mastery < k_skill_mastery_count );
	m_skill_masteries[ skill ] = new_mastery;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_hero_carryover_data::set_spellbook(
	t_spell_set const &	new_spellbook )
{
	m_spellbook = new_spellbook;
}

inline void t_hero_carryover_data::set_use_spellcaster_model( bool arg )
{
	m_use_spellcaster_model = arg;
}

inline bool t_hero_carryover_data::use_spellcaster_model() const
{
	return m_use_spellcaster_model;
}


// --------------------------------------------------------------------------
// structure for basic scenario score keeping
// --------------------------------------------------------------------------
struct t_scenario_score
{
	int		m_score;
	int		m_days;
};


// --------------------------------------------------------------------------
// t_carryover_data class
// --------------------------------------------------------------------------
class t_carryover_data : public t_counted_object
{
public:
	// Types
	typedef t_hero_carryover_data		t_hero_data;
	typedef t_hero_carryover_data_ptr	t_hero_data_ptr;

	// Constructors
	t_carryover_data();
	t_carryover_data( t_carryover_data const & other );

	// Member functions
	void						add( t_artifact const & artifact );
	void						add( t_hero_data_ptr hero_ptr, t_player_color player_color );
	void						add_for_human( t_hero_data_ptr hero_ptr );
	void						add_scenario_score( int score, int days );
	t_scenario_score			get_scenario_score( int scenario_num ) const;
	int							get_scenario_score_count() const;
	bool						read( std::streambuf & stream );
	std::vector< t_artifact >	retrieve_artifacts( t_artifact_set const & artifact_set );
	t_hero_data_ptr				retrieve_most_powerful_hero( t_player_color player_color );
	t_hero_data_ptr				retrieve_most_powerful_hero_for_human();
	t_hero_data_ptr				retrieve_named_hero( std::string const & name );
	bool						write( std::streambuf & stream ) const;

private:
	// Types
	typedef std::vector< t_hero_data_ptr >	t_hero_pool;
	typedef std::vector< t_scenario_score >	t_score_list;

	// Data members
	std::vector< t_artifact >	m_artifact_pool[ k_artifact_type_count ];
	t_hero_pool					m_hero_pools[ k_active_player_color_count ];
	t_hero_pool					m_human_hero_pool;
	t_score_list				m_scenario_scores;

	// Operator
	t_carryover_data & operator=( t_carryover_data const & other ); // Not implemented
};

// --------------------------------------------------------------------------
// t_carryover_data members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_carryover_data::t_carryover_data()
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline void t_carryover_data::add_scenario_score( int score, int days )
{
	// This had better be called in order because we will assume this list is
	// in map number order...
	t_scenario_score record = { score, days };
	m_scenario_scores.push_back( record );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_scenario_score t_carryover_data::get_scenario_score( int scenario_num ) const
{
	assert( scenario_num >= 0 && scenario_num < m_scenario_scores.size() );
	return m_scenario_scores[ scenario_num ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline int t_carryover_data::get_scenario_score_count() const
{
	return m_scenario_scores.size();
}

#endif // !defined( CARRYOVER_DATA_H_INCLUDED )
